package battleship;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.TreeSet;

/**
 *
 * @author Tomek
 */
public abstract class Player{
	private String name;
	public HashSet<Ship> ships = new HashSet<Ship>();
	public HashSet<Coords> missed = new HashSet<Coords>();
	public Grid grid;
	MyTableModel table;
	Random random = new Random();
	Rules rules;
	
	protected void setName(String n) {
		this.name = n;
	}
	public String getName() {
		return this.name;
	}
	
	public HashSet<Ship> getShips() {
		return ships;
	}

	public HashSet<Coords> getMissed() {
		return missed;
	}
	void setActiveFieldsAndToChoose(Set<Field> activeFields, List<Field> toChoose){
		toChoose.clear();
		activeFields.clear();
		for(Field f: grid){
			if(f.fieldType != FieldType.NORMAL) continue;
			activeFields.add(f);
			toChoose.add(f);
		}
	}
	Collection<Ship> setShips(MyTableModel t){
		table = new MyTableModel(t);
		TreeSet<Field> activeFields = new TreeSet<Field>();
		ArrayList<Field> toChoose = new ArrayList<Field>();
		setActiveFieldsAndToChoose(activeFields, toChoose);
		while(t.getRowCount()>0){
			int maxSize = (Integer)t.getValueAt(t.getRowCount()-1, 0);
			Field act = null;
			if(!toChoose.isEmpty())
				act = toChoose.remove(random.nextInt(toChoose.size()));
			while(toChoose.size()>0 &&!activeFields.contains(act)) act = toChoose.remove(random.nextInt(toChoose.size()));
			if(toChoose.isEmpty()){
				//System.out.println("Nie ma gdzie stawiac statkow");
				t = new MyTableModel(table);
				setActiveFieldsAndToChoose(activeFields, toChoose);
				grid.setFieldsType(FieldType.NORMAL);
				ships.clear();
				continue;
			}
			Set<Field> reachable = act.getReachable(activeFields, maxSize, rules.curvedShipsAllowed);
			int sizeOfChoosedField = reachable.size();
			int sizeOfShipToSet = t.getRowCount()-1;
			while(sizeOfShipToSet>=0 && sizeOfChoosedField<(Integer)t.getValueAt(sizeOfShipToSet, 0)) --sizeOfShipToSet;
			if(sizeOfShipToSet==-1){
				for(Field f:reachable){
					activeFields.remove(f);
					f.fieldType = FieldType.INACTIVE;
				}
				continue;
			}
			sizeOfShipToSet = (Integer)t.getValueAt(sizeOfShipToSet, 0);
			Ship s = setShip(sizeOfShipToSet, act, activeFields, reachable);
			t.removeOneShip(sizeOfShipToSet);
			ships.add(s);
		}
		return ships;
	}
	Ship setShip(int size, Field startingPoint, Set<Field> available, Set<Field> line) {
		Field act = startingPoint;
		HashSet<Field> ship = new HashSet<Field>();
		ArrayList<Field> shipMayBeThere = new ArrayList<Field>();
		shipMayBeThere.add(act);
		for(int i=0;i<size; ++i){
			act = shipMayBeThere.remove(random.nextInt(shipMayBeThere.size()));
			ship.add(act);
			available.remove(act);
			if(rules.curvedShipsAllowed){
				for(Field f: act.getNeighbours())
				 if(f.fieldType==FieldType.NORMAL && !ship.contains(f)) shipMayBeThere.add(f);
			}else{
				for(Field f: act.getNeighbours())
				 if(f.fieldType==FieldType.NORMAL && !ship.contains(f) && line.contains(f)) shipMayBeThere.add(f);
			}
		}
		for(Field f: ship){
			if(rules.corneringAllowed)
				for(Field g: f.getNeighbours()){
					available.remove(g);
					g.fieldType = FieldType.INACTIVE;
				}
			else
				for(Field g: f.getNeighboursWithCorners()){
					available.remove(g);
					g.fieldType = FieldType.INACTIVE;
				}
		}
		for(Field f: ship){
			f.fieldType = FieldType.SHIP;
		}
		return new Ship(size, ship);
	}
}
